#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h> 
#include <stdlib.h>       
#include <string.h>
#include <pthread.h>
//#include <sys/sem.h>
#include <errno.h>
#include <sys/ipc.h>
//#include <sys/msg.h>
#include <sys/timeb.h>
#include <sys/socket.h>
//#include <sys/socketvar.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <semaphore.h>
#include <string.h>
#include <termios.h>
#include <linux/input.h>
#include <semaphore.h>
#include <linux/shm.h>
#include <asm/unistd.h>
#include <sys/poll.h>

#include "common.h"


extern SystemParam *pgSystemParam;


#define MAX_COUNT 10 * 1000

static pthread_mutex_t LockChain;
static pthread_mutex_t LockSend;
static pthread_mutex_t LockData;
static int sock = -1;
static struct recvData *recvDataUdp = NULL;
static struct recvData *recvDataBuf = NULL;
static sem_t  taskSem;

static struct internalTask *pTransit										= NULL;//转发服务器 0
static struct internalTask *pDiscover        					= NULL;//发现设备及通信测试 1
static struct internalTask *pSerial          					= NULL;//串口 2
static struct internalTask *pTouchKey       			 			= NULL;//远程控制 3
static struct internalTask *pGpio           						= NULL;//通用IO控制 4
static struct internalTask *pPushVideo		   			 			= NULL;//推送视频 5
static struct internalTask *pCloud2App      			 			= NULL;//转发到上层APP 6
static struct internalTask *pPushAudio									= NULL;//推送音频 7
static struct internalTask *pFile           			 			= NULL;//上传文件 8
static struct internalTask *pSystemState   	  				= NULL;//系统状态:cpu\磁盘等 9
static struct internalTask *pCommand       	  				= NULL;//执行linux命令 A
static struct internalTask *pTerminalConfig        	 	= NULL;//配置 B
static struct internalTask *pBroadcast     					  = NULL;//广播 C
static struct internalTask *pRemoteMonitorAudioVideo		= NULL;//请求监控音视频 D
static struct internalTask *pMicroClass    					  = NULL;//微课请求 E
static struct internalTask *pApp2Cloud									= NULL;//上层APP发数据到设备 F
static struct internalTask *pDeviceAppConfig						= NULL;//设备端APP相关配置 0x10
static struct internalTask *pCtrlOutSys									= NULL;//外部设备（功放、投影仪）开关机0x11
static struct internalTask *pWifi 											= NULL;//wifi 0x1F
static struct internalTask *pAccessCard									= NULL;//门禁卡 0x20


static void* BufServer(void* arg);

void MainServer()
{
		//printf("into MainServer\n");
		int ret;
		socklen_t svrlen;
		struct pollfd pollflag;			
		struct recvData *recvDataTmp = NULL;		
		
		if( ( recvDataUdp = CreateChain(MAX_COUNT) ) == NULL )
		{
				printf("CreateChain error!{%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}
		
		if( pthread_mutex_init (&(LockChain),NULL) != 0   ) 
				printf("pthread_mutex_init failure {%s(%d)}\n",__FILE__,__LINE__);	
		
		if( pthread_mutex_init (&(LockSend),NULL) != 0   ) 
				printf("pthread_mutex_init failure {%s(%d)}\n",__FILE__,__LINE__);	
		
		if( pthread_mutex_init (&(LockData),NULL) != 0   ) 
				printf("pthread_mutex_init failure {%s(%d)}\n",__FILE__,__LINE__);	
				
		if( sem_init(&(taskSem), 1, 0) != 0   ) 
				printf("sem_init failure {%s(%d)}\n",__FILE__,__LINE__);								
	
		if( ( sock = UdpBind(9418) ) < 0 )
		{
				printf("bind error!\n");	
				return;
		}
		
		if( ( pTransit = createTask(transitServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}
		
		if( ( pSerial = createTask(serialServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}
		
		if( ( pTouchKey = createTask(touchKeyServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}
		
		if( ( pGpio = createTask(gpioServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}
		
		if( ( pPushVideo = createTask(pushVideoServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}
		
		if( ( pCloud2App = createTask(cloud2AppServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}
		
		if( ( pPushAudio = createTask(pushAudioServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}

		if( ( pMicroClass = createTask(microClassServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}

		if( ( pFile = createTask(fileServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}

		if( ( pSystemState = createTask(systemStateServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}

		if( ( pCommand = createTask(commandServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}

		if( ( pDiscover = createTask(discoverServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}

		if( ( pTerminalConfig = createTask(terminalConfigServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}

		if( ( pBroadcast = createTask(broadcastServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}
		
		if( ( pApp2Cloud = createTask(app2CloudServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}
		
		if( ( pRemoteMonitorAudioVideo = createTask(remoteMonitorAudioVideoServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}
		
		if( ( pDeviceAppConfig = createTask(deviceAppConfigServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}
		
		if( ( pCtrlOutSys = createTask(ctrlOutSysServer) ) == NULL )
		{
				printf("createTask error! {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}

		if ((pWifi = createTask(wifiServer)) == NULL)
		{
			printf("createTask error! {%s(%d)}\n", __FILE__, __LINE__);
			return;
		}

		if ((pAccessCard = createTask(netACServer)) == NULL)
		{
			printf("createTask error! {%s(%d)}\n", __FILE__, __LINE__);
			return;
		}

		pthread_t ptID;		
						
		if( pthread_create(&ptID, NULL, BufServer, (void *)0) != 0 )
		{
				printf("Make thread failure {%s(%d)}\n",__FILE__,__LINE__);		
				return;
		}			
		
		initHeartbeat(); //初始化心跳	
	
		while( !IsExit() )
		{
			  pollflag.fd      = sock;
			  pollflag.events  = POLLIN;
			  pollflag.revents = 0;	
			  
			  ret = poll( &pollflag, 1, 5000 );	
		
				if( ret == 0 ) 
				{
						continue;
				}	
				
				if( !(pollflag.revents) )	 
				{
						printf("pollflag.revents == 0\n");
						continue;
				}	
				
				#if 0
				pthread_mutex_lock(&(LockChain)); 
				int chain_count=0;
				struct recvData *recvDataBak = recvDataUdp;	
				while(recvDataBak!=NULL)
				{		
						chain_count++;
						recvDataBak = recvDataBak->pNext;	
				}
				pthread_mutex_unlock(&(LockChain));
				#endif
				
				if( recvDataTmp == NULL )
				{
						pthread_mutex_lock(&(LockChain)); 
						recvDataTmp = GetHeadChain(&recvDataUdp);	
						pthread_mutex_unlock(&(LockChain));
				}
				
				static unsigned int addMemoryTime = 0;
				if( recvDataTmp == NULL ) //说明不够，从系统分配
				{
						printf("malloc memory!{%s(%d)}\n",__FILE__,__LINE__);	
						addMemoryTime ++;
						printf("addMemoryTime = %d\n", addMemoryTime);
						
						if( ( recvDataTmp = (struct recvData *)malloc(sizeof(struct recvData)) ) == NULL )	
						{
								printf("insufficient memory!{%s(%d)}\n",__FILE__,__LINE__);	
								return;	
						}		
				}				
				
				recvDataTmp->count = 0;
				recvDataTmp->pNext = NULL;
				svrlen = sizeof(struct sockaddr_in);
				
				recvDataTmp->count = recvfrom(sock, recvDataTmp->buf, 1600, 0, (sockaddr*)&(recvDataTmp->addr), &svrlen);
				if( recvDataTmp->count < 1 )
				{
						printf("recvDataTmp->count < 1\n");
						continue;
				}
		
				pthread_mutex_lock(&(LockData)); 
				InsertTail(&recvDataBuf,recvDataTmp);	
				pthread_mutex_unlock(&(LockData));			

				recvDataTmp = NULL;				
				sem_post(&(taskSem));	
		}

		close(sock);	
}

//先不判断数据包的设备类型是不是云终端
static void oneQeust(struct recvData *recvDataTmp)
{
		if(pgSystemParam->sysRestarting == true)
		{
			printf("system restarting ! reject all recv request !\n");
			RecoveryChain(recvDataTmp);
			return;	
		}
	
		if(recvDataTmp->count < 10)
		{
				printf("recvDataTmp->count < 10 !\n");
				RecoveryChain(recvDataTmp);
				return;	
		}
		
		unsigned char packageStartSign = recvDataTmp->buf[0];
		unsigned char protoVersion[2] = {recvDataTmp->buf[1], recvDataTmp->buf[2]};
		bool isProxy =(((recvDataTmp->buf[3] & (1 << 4)) == 0) && ((recvDataTmp->buf[3] & (1 << 3)) != 0)) ? true:false;
		unsigned char protoMasterType = isProxy ? (recvDataTmp->buf[11]) : (recvDataTmp->buf[5]);
	  unsigned char protoSlaveType = isProxy ? (recvDataTmp->buf[12]) : (recvDataTmp->buf[6]);
		//printf("recvDataTmp->buf[3] = %d, protoMasterType,protoSlaveType = %d,%d {%s,%d}\n", recvDataTmp->buf[3], protoMasterType,protoSlaveType,__FILE__, __LINE__);
		
		//char *ip = inet_ntoa(recvDataTmp->addr.sin_addr);
		//unsigned short port = recvDataTmp->addr.sin_port;
		//if(strstr(ip, "59.")) printf("ip,port=%s,%d\n", ip,port);
		
		/*unsigned char *revData = recvDataTmp->buf;
		if(recvDataTmp->count == 38)
		{
					printf("revData = ");
					for(unsigned char i = 0; i<38; i++)
					{
							printf("%x ", revData[i]);
					}			
					printf("\n");
					
					if(isProxy) printf("isProxy==true\n");
					else printf("isProxy==false\n");
					
					printf("protoMasterType,protoSlaveType=%d,%d\n", protoMasterType,protoSlaveType);
		}*/
		
		//if(recvDataTmp->buf[3] == 0x10)
		//{
		//		printf("recvDataTmp->buf[3] == 0x10 protoMasterType,protoSlaveType, = %x,%x\n", protoMasterType,protoSlaveType);	
		//}
		
		if(packageStartSign != 0xFF) //无效数据，直接扔回去回收
		{
				printf("packageStartSign != 0xFF\n");
				RecoveryChain(recvDataTmp);
				return;
		}
		
		if((protoVersion[0] != 0) || (protoVersion[1] != 0)) //需要解密之类的操作。。
		{
				//	
		}

		switch(protoMasterType)
		{
				case 0x00:
						PushTask(pTransit,recvDataTmp);
						break;
				case 0x01:
						PushTask(pDiscover,recvDataTmp);					
						break;
				case 0x02:
						PushTask(pSerial,recvDataTmp);					
						break;
				case 0x03:
						PushTask(pTouchKey,recvDataTmp);
						break;
				case 0x04:
						PushTask(pGpio,recvDataTmp);						
						break;
				case 0x05:
						PushTask(pPushVideo,recvDataTmp);					
						break;
				case 0x06:
						PushTask(pCloud2App,recvDataTmp);					
						break;
				case 0x07:
						PushTask(pPushAudio,recvDataTmp);						
						break;
				case 0x08:
						PushTask(pFile,recvDataTmp);					
						break;
				case 0x09:
						PushTask(pSystemState,recvDataTmp);				
						break;
				case 0x0A:
						PushTask(pCommand,recvDataTmp);				
						break;
				case 0x0B:
						PushTask(pTerminalConfig,recvDataTmp);						
						break;
				case 0x0C:
						PushTask(pBroadcast,recvDataTmp);					
						break;
				case 0x0D:
						PushTask(pRemoteMonitorAudioVideo,recvDataTmp);						
						break;
				case 0x0E:
						PushTask(pMicroClass,recvDataTmp);					
						break;
				case 0x0F:
						PushTask(pApp2Cloud,recvDataTmp);					
						break;
				case 0x10:
						PushTask(pDeviceAppConfig,recvDataTmp);	
						break;
				case 0x11:
						PushTask(pCtrlOutSys,recvDataTmp);	
						break;
				case 0x1F:
						PushTask(pWifi, recvDataTmp);
						break;
				case 0x20:
						PushTask(pAccessCard, recvDataTmp);
						break;
				default: //都没人要则回收
						RecoveryChain(recvDataTmp);					
						break;
		}
}

static void* BufServer(void* arg)
{
		struct recvData *recvDataTmp = NULL;
		struct recvData *recvDataBak = NULL;
		struct timespec ts;
		struct timeval  tv;					
		static unsigned int dealTimes = 0;
		while( !IsExit() )
		{
				gettimeofday(&tv, NULL); 
				
			  ts.tv_sec  = tv.tv_sec + 2;
		    ts.tv_nsec = tv.tv_usec * 1000;		
		    
		    if( sem_timedwait(&(taskSem),&ts) != 0 )	continue;	
		    
		    pthread_mutex_lock(&(LockData)); 
				recvDataTmp = recvDataBuf;
				recvDataBuf = NULL;
				pthread_mutex_unlock(&(LockData));		

				while( recvDataTmp != NULL )
				{
						recvDataBak = recvDataTmp;
						recvDataTmp = recvDataTmp->pNext;	
						recvDataBak->pNext = NULL;
						
						oneQeust(recvDataBak);										
				}
		}		
	
		return 0;	
}

int MainSend(unsigned char *data,int size,struct sockaddr_in *paddr)
{
		socklen_t svrlen = sizeof(struct sockaddr_in);	
		
		pthread_mutex_lock(&(LockSend)); 	
					
		while( sendto(sock,data,size,0,(const sockaddr*)paddr,svrlen) != size);
	
		pthread_mutex_unlock(&(LockSend));	
		
		return 0;	
}

void RecoveryChain(struct recvData *src)
{
		pthread_mutex_lock(&(LockChain)); 
		InsertHead(&recvDataUdp,src);	
		pthread_mutex_unlock(&(LockChain));	
}
